package list

import (
	"errors"
	"sync"
)

type arrayList struct {
	data []interface{}
	lock sync.Mutex
}

func NewArrayList() *arrayList {
	return &arrayList{
		data: make([]interface{}, 0),
		lock: sync.Mutex{},
	}
}

func NewArrayListWithData(data []interface{}) *arrayList {
	return &arrayList{
		data: data,
		lock: sync.Mutex{},
	}
}

func (a *arrayList) Size() int {
	return len(a.data)
}

func (a *arrayList) IsEmpty() bool {
	return len(a.data) == 0
}

func (a *arrayList) Contains(data interface{}) bool {
	if a == nil || len(a.data) == 0 {
		return false
	}

	for _, v := range a.data {
		if v == data {
			return true
		}
	}
	return false
}

func (a *arrayList) ToArray() []interface{} {
	return nil
}

func (a *arrayList) Add(data interface{}) bool {
	a.lock.Lock()
	defer a.lock.Unlock()

	a.data = append(a.data, data)
	return true
}

func (a *arrayList) Remove(data interface{}) (bool, error) {
	a.lock.Lock()
	defer a.lock.Unlock()

	if a.IsEmpty() {
		return false, errors.New("Arraylist is empty")
	}

	res := make([]interface{}, len(a.data))

	index := -1
	for i, v := range a.data {
		if data == v {
			index = i
			break
		}
	}

	if index == -1 {
		return false, errors.New("obj is not exist in Arraylist")
	}

	if index == 0 {
		res = a.data[1:]
	} else {
		res = append(a.data[:index], a.data[index-1:])
	}

	a.data = res
	return true, nil
}

func (a *arrayList) AddAll(data []interface{}) bool {
	if data != nil && len(data) > 0 {
		a.data = append(a.data, data)
	}
	return false
}

func (a *arrayList) Clear() {
	a.data = make([]interface{}, 0)
}

// -1表示不存在
func (a *arrayList) IndexOf(data interface{}) int {
	index := -1

	if len(a.data) == 0 {
		return index
	}

	for i, v := range a.data {
		if v == data {
			index = i
			break
		}
	}
	return index
}

func (a *arrayList) LastIndexOf(data interface{}) int {
	index := -1
	if len(a.data) == 0 {
		return index
	}

	for i := len(a.data) - 1; i >= 0; i-- {
		if a.data[i] == data {
			index = i
			break
		}
	}
	return index
}

func (a *arrayList) SubList(formIndex, toIndex int) ([]interface{}, error) {
	if formIndex < 0 || toIndex > len(a.data) || len(a.data) == 0 {
		return nil, errors.New("illeage params")
	}
	return a.data[formIndex:toIndex], nil
}

func (a *arrayList) Get(index int) interface{} {
	if index < 0 || index > len(a.data) || a.IsEmpty() {
		return nil
	}

	return a.data[index]
}

func (a *arrayList) Set(index int, data interface{}) bool {
	if index < 0 || index > len(a.data) {
		return false
	}

	a.data[index] = data
	return true
}
